package com.example.edu.Service.Impl;

import com.example.edu.Dto.PictureUploadDtoG;
import com.example.edu.Dto.Return;
import com.example.edu.Entity.Picture;
import com.example.edu.Mapper.PictureMapper;
import com.example.edu.Service.PictureService;
import com.example.edu.Utils.CacheDataBaseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import static com.example.edu.Utils.MyConstants.*;

@Service
public class PictureServiceImpl implements PictureService {
    @Resource
    PictureMapper pictureMapper;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    CacheDataBaseUtil cacheDataBaseUtil;
    private static final Logger logger = LoggerFactory.getLogger(PictureServiceImpl.class);

    @Override
    @Transactional
    public Return upload(PictureUploadDtoG pictureUploadData) {
        try {
            return upload1(pictureUploadData);
        } catch (Exception e){
            return Return.fail(1,"上传失败");
        }
    }

    @Transactional
    public Return upload1(PictureUploadDtoG pictureUploadData) {
        String md5 = pictureUploadData.getKey();
        String type = pictureUploadData.getType();
        //尝试获取锁
        if(!cacheDataBaseUtil.tryLock("picture_upload",md5,LOCK_TTL, TimeUnit.MINUTES))
            return Return.fail(2,"用户较多，请稍后重试");
        try {
            // 若服务器中有该图片，则不需要存储图片，返回url即可
            if (cacheDataBaseUtil.isContainsById(PICTURE_KEY, md5, md52 -> pictureMapper.getPictureId(md52), PICTURE_CACHE_TTL, TimeUnit.HOURS)) {
                int picture_id = cacheDataBaseUtil.selectById(PICTURE_KEY, md5, Integer.class, md52 -> pictureMapper.getPictureId(md52), PICTURE_CACHE_TTL, TimeUnit.HOURS);
                return Return.ok(BASE_URL + PICTURE_ADDRESS + "/" + picture_id + "." + type);
            }
            // 否则上传图片，添加图片信息到数据库，并建立和用户的联系
            MultipartFile picture = pictureUploadData.getPicture();
            Picture picture_message = new Picture(-1,md5,type);
            pictureMapper.addPicture(picture_message);
            stringRedisTemplate.opsForValue().set(PICTURE_KEY + md5, String.valueOf(picture_message.getPicture_id()), PICTURE_CACHE_TTL, TimeUnit.HOURS);
            try {
                String path = PICTURE_ADDRESS + "/" + picture_message.getPicture_id() + "." + type;
                File dest = new File(path);
                picture.transferTo(dest);
                return Return.ok(BASE_URL + path);
            } catch (IOException e) {
                logger.error(e.getMessage());
                throw new RuntimeException(e);
            }
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
        finally {
            cacheDataBaseUtil.unlock("picture_upload",md5);
        }
    }
}
